﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Assets.Scripts.ProceduralCityGenerator;
using UnityEngine;
using UnityEngine.Networking;

// Token: 0x02000335 RID: 821
public class CityBuilder : EntityBase
{
	// Token: 0x06001532 RID: 5426 RVA: 0x00089F9A File Offset: 0x0008819A
	protected override void Awake()
	{
		base.Awake();
		this.rotationEnabled = false;
		this.Init();
	}

	// Token: 0x06001533 RID: 5427 RVA: 0x00089FB0 File Offset: 0x000881B0
	private void Init()
	{
		this.mainCamera = Camera.main;
		this.placeHolder = this.myTransform.GetChild(0);
		this.UpdatePreview();
		this.buildings0 = Resources.LoadAll<GameObject>("City/Building/Zone0");
		this.buildings1 = Resources.LoadAll<GameObject>("City/Building/Zone1");
		this.buildings2 = Resources.LoadAll<GameObject>("City/Building/Zone2");
		foreach (GameObject building in this.buildings0)
		{
			this.InitializeBuilding(building);
		}
		foreach (GameObject building2 in this.buildings1)
		{
			this.InitializeBuilding(building2);
		}
		foreach (GameObject building3 in this.buildings2)
		{
			this.InitializeBuilding(building3);
		}
		this.intersectionPrefab = Resources.Load<GameObject>("City/Road/Intersection");
		this.junctionPrefab = Resources.Load<GameObject>("City/Road/Junction");
		this.straightPrefab = Resources.Load<GameObject>("City/Road/Straight");
		this.curvePrefab = Resources.Load<GameObject>("City/Road/Curve");
		this.endPrefab = Resources.Load<GameObject>("City/Road/End");
		this.ColliderPrefab = Resources.Load<GameObject>("City/CityColliderZone");
		this.audioSource = base.gameObject.AddComponent<AudioSource>();
		this.audioSource.dopplerLevel = 0f;
		this.audioSource.spatialBlend = 0f;
		this.audioSource.outputAudioMixerGroup = SoundManager.mg_background;
		this.minSoundDistance = (float)this.radius * this.tileSize;
		this.maxSoundDistance = (float)this.radius * this.tileSize * 2f;
		this.ResetCity();
	}

	// Token: 0x06001534 RID: 5428 RVA: 0x0008A16C File Offset: 0x0008836C
	private void ResetCity()
	{
		if (this.roadRoot != null)
		{
			UnityEngine.Object.Destroy(this.roadRoot);
		}
		if (this.buildingRoot != null)
		{
			UnityEngine.Object.Destroy(this.buildingRoot);
		}
		if (this.floorRoot != null)
		{
			UnityEngine.Object.Destroy(this.floorRoot);
		}
		this.colliderList = new Collider[0];
		this.buildingRoot = new GameObject("Buildings");
		this.buildingRoot.transform.SetParent(base.transform, false);
		this.roadRoot = new GameObject("Roads");
		this.roadRoot.transform.SetParent(base.transform, false);
		this.placeHolder.gameObject.SetActive(true);
		this.isPlaced = false;
	}

	// Token: 0x06001535 RID: 5429 RVA: 0x0008A240 File Offset: 0x00088440
	private void ResetCityLod()
	{
		float magnitude = (this.mainCamera.transform.position - base.transform.position).magnitude;
		if (magnitude < this.maxVisibleDistanceRoad)
		{
			this.MakeRoadsVisible(true);
		}
		else
		{
			this.MakeRoadsVisible(false);
		}
		if (magnitude < this.maxVisibleDistance)
		{
			this.MakeBuildingsVisible(true);
		}
		else
		{
			this.MakeBuildingsVisible(false);
		}
	}

	// Token: 0x06001536 RID: 5430 RVA: 0x0008A2B4 File Offset: 0x000884B4
	public override void Move(Vector3 position)
	{
		if (this.isPlaced)
		{
			this.ResetCity();
		}
		base.Move(position);
	}

	// Token: 0x06001537 RID: 5431 RVA: 0x00002973 File Offset: 0x00000B73
	public override void ChangeRotation(Vector3 newRotation)
	{
	}

	// Token: 0x06001538 RID: 5432 RVA: 0x00002973 File Offset: 0x00000B73
	public override void ChangeOffset(float newOffset)
	{
	}

	// Token: 0x06001539 RID: 5433 RVA: 0x0008A2CE File Offset: 0x000884CE
	public override void ChangeScale(float newScale)
	{
		if (!this.isPlaced)
		{
			base.ChangeScale(newScale);
		}
	}

	// Token: 0x0600153A RID: 5434 RVA: 0x0008A2E4 File Offset: 0x000884E4
	public override void OnPlaced()
	{
		GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(Resources.Load("UI/CityGeneratorUi") as GameObject);
		GameController component = Camera.main.GetComponent<GameController>();
		gameObject.transform.SetParent(component.view.mainCanvas.transform, false);
		this.creationPopup = gameObject.AddComponent<CityCreationPopUp>();
		this.creationPopup.SetHandlers(new Action(this.BuildCity), new Action(this.Cancel), new Action(this.UpdatePreview));
	}

	// Token: 0x0600153B RID: 5435 RVA: 0x0008A368 File Offset: 0x00088568
	private void UpdateCreationValues()
	{
		if (this.creationPopup == null)
		{
			return;
		}
		this.populationOffset = (float)(this.creationPopup.PopModifierValue / 250);
		this.radius = this.creationPopup.CityRadiusValue;
		this.buildingHeightBonus = (float)this.creationPopup.SkyScraperHeightValue;
		this.scaleNoise = (float)this.creationPopup.OpenSpaceChanceValue / 100f * 8f;
		this.AutoPopulate = this.creationPopup.AutoPoplulate;
		this.mLowEndMode = GlobalPreferences.LowEndCities.value;
		this.seedExists = !string.IsNullOrEmpty(this.creationPopup.SeedValue);
		if (this.seedExists)
		{
			this.cityGenSeed = this.creationPopup.SeedValue.GetHashCode();
		}
	}

	// Token: 0x0600153C RID: 5436 RVA: 0x0008A43C File Offset: 0x0008863C
	private void UpdatePreview()
	{
		this.UpdateCreationValues();
		this.placeHolder.localScale = new Vector3((float)this.radius * this.tileSize * 1.4f, this.previewBuildingHeight * (1f + this.buildingHeightBonus / 100f), (float)this.radius * this.tileSize * 1.4f);
	}

	// Token: 0x0600153D RID: 5437 RVA: 0x0008A4A0 File Offset: 0x000886A0
	private void Cancel()
	{
		UnityEngine.Object.Destroy(base.gameObject);
	}

	// Token: 0x0600153E RID: 5438 RVA: 0x0008A4B0 File Offset: 0x000886B0
	private GameObject CloneBuildingPrefab(GameObject building, bool cloneChunks)
	{
		GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(building);
		if (!cloneChunks)
		{
			for (int i = 0; i < gameObject.transform.childCount; i++)
			{
				Transform child = gameObject.transform.GetChild(i);
				if (child.name == "Chunks")
				{
					UnityEngine.Object.Destroy(child.gameObject);
					break;
				}
			}
		}
		gameObject.transform.position += new Vector3(0f, -400f, 0f);
		return gameObject;
	}

	// Token: 0x0600153F RID: 5439 RVA: 0x0008A544 File Offset: 0x00088744
	private void BuildCity()
	{
		this.placeHolder.gameObject.SetActive(false);
		this.UpdateCreationValues();
		if (this.AutoPopulate)
		{
			Vector3 position = this.placeHolder.position;
			Vector3 lossyScale = this.placeHolder.lossyScale;
			this.PopManager = this.buildingRoot.AddComponent<CityPopulationManager>();
			this.PopManager.SetParameters(position, lossyScale, this.buildingRoot, base.Scale);
		}
		else
		{
			this.PopManager = null;
		}
		if (this.seedExists)
		{
			UnityEngine.Random.InitState(this.cityGenSeed);
		}
		if (!this.mLowEndMode)
		{
			this.mDestructionManager = this.buildingRoot.AddComponent<CityDestructionManager>();
			this.mDestructionManager.CityManager = this.PopManager;
		}
		for (int i = 0; i < this.buildings0.Length; i++)
		{
			this.buildings0[i] = this.SetBuildingPrefabs(this.buildings0[i]);
		}
		for (int j = 0; j < this.buildings1.Length; j++)
		{
			this.buildings1[j] = this.SetBuildingPrefabs(this.buildings1[j]);
		}
		for (int k = 0; k < this.buildings2.Length; k++)
		{
			this.buildings2[k] = this.SetBuildingPrefabs(this.buildings2[k]);
		}
		this.creationPopup = null;
		this.cityScale = base.transform.lossyScale.y;
		if (base.transform.parent != null)
		{
			this.parentCollider = base.transform.parent.GetComponent<Collider>();
		}
		else
		{
			this.parentCollider = null;
		}
		this.diameter = this.radius * 2 + 1;
		this.perlinValue = this.SamplePerlinNoise(this.diameter);
		this.tiles = new CityBuilder.Tile[this.diameter, this.diameter];
		base.StartCoroutine(this.ExecuteCityBuilding());
	}

	// Token: 0x06001540 RID: 5440 RVA: 0x0008A738 File Offset: 0x00088938
	private GameObject SetBuildingPrefabs(GameObject building)
	{
		GameObject gameObject = this.CloneBuildingPrefab(building, !this.mLowEndMode);
		this.InitializeBuilding(gameObject);
		return gameObject;
	}

	// Token: 0x06001541 RID: 5441 RVA: 0x0008A760 File Offset: 0x00088960
	private IEnumerator ExecuteCityBuilding()
	{
		this.DetermineBuildableArea();
		yield return null;
		this.CreateStreets();
		yield return null;
		this.CreateFloor();
		yield return null;
		while (!this.CreateBuildings())
		{
			yield return null;
		}
		yield return null;
		if (this.AutoPopulate)
		{
			GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this.ColliderPrefab);
			gameObject.transform.localScale = this.placeHolder.transform.localScale;
			gameObject.transform.position = this.placeHolder.transform.position;
			gameObject.transform.parent = base.transform;
			this.PopManager.SetTriggerZone(gameObject);
			this.PopManager.PopStart();
		}
		this.isPlaced = true;
		this.ResetCityLod();
		if (this.mLowEndMode)
		{
			for (int i = 0; i < this.buildings0.Length; i++)
			{
				UnityEngine.Object.Destroy(this.buildings0[i]);
			}
			for (int j = 0; j < this.buildings1.Length; j++)
			{
				UnityEngine.Object.Destroy(this.buildings1[j]);
			}
			for (int k = 0; k < this.buildings2.Length; k++)
			{
				UnityEngine.Object.Destroy(this.buildings2[k]);
			}
		}
		yield break;
	}

	// Token: 0x06001542 RID: 5442 RVA: 0x0008A77C File Offset: 0x0008897C
	private void DetermineBuildableArea()
	{
		for (int i = -this.radius; i < this.radius; i++)
		{
			for (int j = -this.radius; j < this.radius; j++)
			{
				int num = i + this.radius;
				int num2 = j + this.radius;
				CityBuilder.Tile tile = new CityBuilder.Tile(i, j);
				tile.ux = num;
				tile.uy = num2;
				if (this.perlinValue[num, num2] > CityBuilder.cPerlinThreshold)
				{
					tile.type = CityBuilder.TileType.CanBuild;
				}
				else
				{
					tile.type = CityBuilder.TileType.NoBuild;
				}
				this.tiles[num, num2] = tile;
			}
		}
	}

	// Token: 0x06001543 RID: 5443 RVA: 0x0008A82C File Offset: 0x00088A2C
	private void CreateStreets()
	{
		this.intersections = new List<CityBuilder.Tile>();
		for (int i = -this.radius; i < this.radius; i++)
		{
			for (int j = -this.radius; j < this.radius; j++)
			{
				int num = i + this.radius;
				int num2 = j + this.radius;
				CityBuilder.Tile tile = this.tiles[num, num2];
				if (tile.type == CityBuilder.TileType.CanBuild)
				{
					if ((i % this.streetModule == 0 || j % this.streetModule == 0) && i % this.streetModule == 0 && j % this.streetModule == 0 && this.PlanIntersection(tile))
					{
						this.CheckCloseIntersection(num, num2);
						this.intersections.Add(tile);
					}
				}
			}
		}
		foreach (CityBuilder.Tile tile2 in this.intersections)
		{
			this.SpawnIntersection(tile2);
		}
		StaticBatchingUtility.Combine(this.roadRoot);
	}

	// Token: 0x06001544 RID: 5444 RVA: 0x0008A968 File Offset: 0x00088B68
	private void CreateFloor()
	{
		List<Vector3> list = new List<Vector3>();
		List<int> list2 = new List<int>();
		List<Vector2> list3 = new List<Vector2>();
		foreach (CityBuilder.Tile tile in this.intersections)
		{
			int ux = tile.ux;
			int uy = tile.uy;
			if (uy + this.streetModule < this.diameter && ux + this.streetModule < this.diameter)
			{
				CityBuilder.Tile[] array = new CityBuilder.Tile[]
				{
					this.tiles[ux, uy + this.streetModule],
					this.tiles[ux + this.streetModule, uy],
					this.tiles[ux + this.streetModule, uy + this.streetModule]
				};
				if (array[0].type == CityBuilder.TileType.Intersection && array[1].type == CityBuilder.TileType.Intersection && array[2].type == CityBuilder.TileType.Intersection)
				{
					int count = list.Count;
					Vector3 item = tile.localPosition + new Vector3(this.tileSize * 0.5f, this.floorOffset, this.tileSize * 0.5f);
					Vector3 item2 = array[0].localPosition + new Vector3(this.tileSize * 0.5f, this.floorOffset, -this.tileSize * 0.5f);
					Vector3 item3 = array[2].localPosition + new Vector3(-this.tileSize * 0.5f, this.floorOffset, -this.tileSize * 0.5f);
					Vector3 item4 = array[1].localPosition + new Vector3(-this.tileSize * 0.5f, this.floorOffset, this.tileSize * 0.5f);
					list.Add(item);
					list.Add(item2);
					list.Add(item3);
					list.Add(item4);
					list3.Add(new Vector2(0f, 0f));
					list3.Add(new Vector2(1f, 0f));
					list3.Add(new Vector2(1f, 1f));
					list3.Add(new Vector2(0f, 1f));
					list2.Add(count);
					list2.Add(count + 1);
					list2.Add(count + 2);
					list2.Add(count);
					list2.Add(count + 2);
					list2.Add(count + 3);
				}
			}
		}
		this.floorRoot = new GameObject("Floor");
		this.floorRoot.layer = Layers.mapLayer;
		this.floorRoot.transform.SetParent(base.transform, false);
		MeshFilter meshFilter = this.floorRoot.AddComponent<MeshFilter>();
		MeshRenderer meshRenderer = this.floorRoot.AddComponent<MeshRenderer>();
		MeshCollider meshCollider = this.floorRoot.AddComponent<MeshCollider>();
		Mesh mesh = new Mesh();
		mesh.SetVertices(list);
		mesh.SetTriangles(list2, 0);
		mesh.SetUVs(0, list3);
		mesh.RecalculateNormals();
		mesh.RecalculateBounds();
		meshFilter.sharedMesh = mesh;
		meshCollider.sharedMesh = mesh;
		meshRenderer.material = this.floorMaterial;
	}

	// Token: 0x06001545 RID: 5445 RVA: 0x0008ACD0 File Offset: 0x00088ED0
	private bool CreateBuildings()
	{
		if (this.buildingCreationCache.NeedsReInit)
		{
			this.buildingCreationCache.X = -this.radius;
			this.buildingCreationCache.Y = -this.radius;
			this.buildingCreationCache.NeedsReInit = false;
		}
		int num = 0;
		Stopwatch stopwatch = new Stopwatch();
		stopwatch.Start();
		for (int i = this.buildingCreationCache.X; i < this.radius; i++)
		{
			this.buildingCreationCache.X = i;
			for (int j = this.buildingCreationCache.Y; j < this.radius; j++)
			{
				int num2 = i + this.radius;
				int num3 = j + this.radius;
				if (this.tiles[num2, num3].type == CityBuilder.TileType.CanBuild)
				{
					this.InstantiateBuilding(i, j, this.GenerateBuildingHeight(num2, num3));
					num++;
				}
				this.buildingCreationCache.Y = j;
				if (num > this.cellsPerCycle)
				{
					stopwatch.Stop();
					this.RecalculateSreamingLoad(stopwatch.ElapsedMilliseconds);
					return false;
				}
			}
			this.buildingCreationCache.Y = -this.radius;
		}
		stopwatch.Stop();
		return true;
	}

	// Token: 0x06001546 RID: 5446 RVA: 0x0008AE04 File Offset: 0x00089004
	private void RecalculateSreamingLoad(long pastMs)
	{
		if (pastMs < 20L)
		{
			this.cellsPerCycle++;
		}
		else if (pastMs > 12L && this.cellsPerCycle > 1)
		{
			this.cellsPerCycle--;
		}
	}

	// Token: 0x06001547 RID: 5447 RVA: 0x0008AE50 File Offset: 0x00089050
	private float GenerateBuildingHeight(int x, int y)
	{
		float num = this.perlinValue[x, y];
		return num + this.populationOffset;
	}

	// Token: 0x06001548 RID: 5448 RVA: 0x0008AE74 File Offset: 0x00089074
	private void Update()
	{
		float num = (this.mainCamera.transform.position - base.transform.position).magnitude;
		num /= base.Scale;
		if (num < this.maxSoundDistance && !this.audioSource.isPlaying)
		{
			this.audioSource.clip = SoundManager.This.GetCitySoundPeaceful();
			this.audioSource.Play();
		}
		if (num < this.minSoundDistance)
		{
			this.audioSource.volume = SoundManager.ambientVolume;
		}
		else if (num < this.maxSoundDistance)
		{
			this.audioSource.volume = SoundManager.ambientVolume * (1f - (num - this.minSoundDistance) / (this.maxSoundDistance - this.minSoundDistance));
		}
		else
		{
			this.audioSource.volume = 0f;
			this.audioSource.Stop();
		}
		SoundManager.This.ambientLevel = 1f - this.audioSource.volume / SoundManager.ambientVolume;
		if (!this.isBuildingsVisible && num < this.maxVisibleDistance)
		{
			this.MakeBuildingsVisible(true);
		}
		else if (this.isBuildingsVisible && num > this.maxVisibleDistance)
		{
			this.MakeBuildingsVisible(false);
		}
		if (!this.isRoadsVisible && num < this.maxVisibleDistanceRoad)
		{
			this.MakeRoadsVisible(true);
		}
		else if (this.isRoadsVisible && num > this.maxVisibleDistanceRoad)
		{
			this.MakeRoadsVisible(false);
		}
	}

	// Token: 0x06001549 RID: 5449 RVA: 0x0008B00C File Offset: 0x0008920C
	private void MakeBuildingsVisible(bool visible)
	{
		if (!this.buildingRoot || !this.floorRoot)
		{
			return;
		}
		Renderer[] componentsInChildren = this.buildingRoot.GetComponentsInChildren<Renderer>();
		componentsInChildren.All(delegate(Renderer x)
		{
			bool visible2 = visible;
			x.enabled = visible2;
			return visible2;
		});
		MeshRenderer component = this.floorRoot.GetComponent<MeshRenderer>();
		if (visible)
		{
			component.material = this.floorMaterial;
		}
		else
		{
			component.material = this.lowPoly;
		}
		this.isBuildingsVisible = visible;
	}

	// Token: 0x0600154A RID: 5450 RVA: 0x0008B0A8 File Offset: 0x000892A8
	private void MakeRoadsVisible(bool visible)
	{
		if (!this.roadRoot)
		{
			return;
		}
		Renderer[] componentsInChildren = this.roadRoot.GetComponentsInChildren<Renderer>();
		componentsInChildren.All(delegate(Renderer x)
		{
			bool visible2 = visible;
			x.enabled = visible2;
			return visible2;
		});
		this.isRoadsVisible = visible;
	}

	// Token: 0x0600154B RID: 5451 RVA: 0x0008B100 File Offset: 0x00089300
	private void InitializeBuilding(GameObject building)
	{
		building.gameObject.layer = Layers.buildingLayer;
		CityBuilding x = building.GetComponent<CityBuilding>();
		if (x == null)
		{
			x = building.AddComponent<CityBuilding>();
		}
	}

	// Token: 0x0600154C RID: 5452 RVA: 0x0008B138 File Offset: 0x00089338
	private GameObject InstantiateBuilding(int x, int y, float buildingValue)
	{
		if (this.seedExists)
		{
			UnityEngine.Random.InitState(x * 2 * (y * 3) * this.cityGenSeed);
		}
		if (UnityEngine.Random.value > this.buildingDensity)
		{
			return null;
		}
		int num = x + this.radius;
		int num2 = y + this.radius;
		int num3 = UnityEngine.Random.Range(0, 4);
		bool flag = num3 == 1 || num3 == 3;
		GameObject gameObject;
		if (buildingValue > 0.8f)
		{
			int num4 = UnityEngine.Random.Range(0, this.buildings2.Length);
			gameObject = this.buildings2[num4];
		}
		else if (buildingValue > 0.5f)
		{
			int num5 = UnityEngine.Random.Range(0, this.buildings1.Length);
			gameObject = this.buildings1[num5];
		}
		else
		{
			int num6 = UnityEngine.Random.Range(0, this.buildings0.Length);
			gameObject = this.buildings0[num6];
		}
		Vector3 one;
		if (buildingValue > 0.5f)
		{
			float num7 = 1f;
			num7 += this.buildScaleModification * (2f * UnityEngine.Random.value - 1f);
			num7 *= 1f + this.buildingHeightBonus / 100f;
			one = new Vector3(1f, num7, 1f);
		}
		else
		{
			one = Vector3.one;
		}
		CityBuilding component = gameObject.GetComponent<CityBuilding>();
		int num8 = component.xSize;
		int num9 = component.zSize;
		if (flag)
		{
			num8 = num9;
			num9 = component.xSize;
		}
		if (num + num8 > this.diameter || num2 + num9 > this.diameter)
		{
			return null;
		}
		for (int i = num; i < num + num8; i++)
		{
			for (int j = num2; j < num2 + num9; j++)
			{
				if (this.tiles[i, j].type != CityBuilder.TileType.CanBuild)
				{
					return null;
				}
			}
		}
		Vector3[] array = this.CalculateCorners(this.tiles[num, num2], num8, num9);
		Vector3 vector = array[4];
		bool flag2 = false;
		for (int k = 0; k < array.Length; k++)
		{
			Vector3 origin = base.transform.TransformPoint(array[k] + Vector3.up * this.superiorLimit);
			RaycastHit raycastHit;
			if (Physics.Raycast(origin, -Vector3.up, out raycastHit, (this.superiorLimit + this.inferiorLimit) * this.cityScale))
			{
				Vector3 vector2 = base.transform.InverseTransformPoint(raycastHit.point);
				if (!flag2 || vector2.y < vector.y)
				{
					vector.y = vector2.y;
					float num10 = Mathf.Abs(Vector3.Angle(Vector3.up, raycastHit.normal));
					if (num10 > this.maxSlope)
					{
						return null;
					}
					flag2 = true;
				}
			}
		}
		if (!flag2)
		{
			return null;
		}
		for (int l = num; l < num + num8; l++)
		{
			for (int m = num2; m < num2 + num9; m++)
			{
				this.tiles[l, m].type = CityBuilder.TileType.Occupied;
			}
		}
		GameObject gameObject2 = UnityEngine.Object.Instantiate<GameObject>(gameObject);
		gameObject2.transform.SetParent(this.buildingRoot.transform, false);
		gameObject2.transform.localPosition = vector;
		gameObject2.transform.localRotation = Quaternion.AngleAxis(90f * (float)num3, Vector3.up);
		gameObject2.transform.localScale = one;
		CityBuilding component2 = gameObject2.GetComponent<CityBuilding>();
		component2.Position = vector;
		component2.LowEnd = this.mLowEndMode;
		component2.DestructionManager = this.mDestructionManager;
		if (this.parentCollider != null)
		{
			gameObject2.GetComponent<CityBuilding>().IgnoreCollision(this.parentCollider);
		}
		if (this.PopManager != null)
		{
			CityBuilding component3 = gameObject2.GetComponent<CityBuilding>();
			Vector3[] array2 = new Vector3[array.Length];
			for (int n = 0; n < array.Length; n++)
			{
				array2[n] = base.transform.TransformPoint(array[n]);
			}
			component3.CellArea = array2;
			this.PopManager.AddBuilding(component3);
		}
		this.DisableSmokeIfRequired(gameObject2);
		return gameObject2;
	}

	// Token: 0x0600154D RID: 5453 RVA: 0x0008B598 File Offset: 0x00089798
	private void DisableSmokeIfRequired(GameObject building)
	{
		if (!this.mLowEndMode && !GlobalPreferences.SmokeEnabled.value)
		{
			for (int i = 0; i < building.transform.childCount; i++)
			{
				Transform child = building.transform.GetChild(i);
				if (child.name == "Chunks")
				{
					FracturedObject component = child.GetComponent<FracturedObject>();
					component.EventExplosionPrefabsArray = new FracturedObject.PrefabInfo[0];
					component.EventDetachPrefabsArray = new FracturedObject.PrefabInfo[0];
					component.EventImpactPrefabsArray = new FracturedObject.PrefabInfo[0];
					component.EventDetachedPrefabsArray = new FracturedObject.PrefabInfo[0];
					break;
				}
			}
		}
	}

	// Token: 0x0600154E RID: 5454 RVA: 0x0008B63C File Offset: 0x0008983C
	private Vector3[] CalculateCorners(CityBuilder.Tile tile, int xSize = 1, int zSize = 1)
	{
		Vector3[] array = new Vector3[5];
		array[0] = new Vector3((float)tile.x * this.tileSize - this.tileSize / 2f, 0f, (float)tile.y * this.tileSize - this.tileSize / 2f);
		array[1] = array[0] + new Vector3(0f, 0f, this.tileSize * (float)zSize);
		array[2] = array[0] + new Vector3(this.tileSize * (float)xSize, 0f, 0f);
		array[3] = array[0] + new Vector3(this.tileSize * (float)xSize, 0f, this.tileSize * (float)zSize);
		array[4] = (array[0] + array[3]) / 2f;
		return array;
	}

	// Token: 0x0600154F RID: 5455 RVA: 0x0008B774 File Offset: 0x00089974
	private bool PlanIntersection(CityBuilder.Tile tile)
	{
		Vector3[] array = this.CalculateCorners(tile, 1, 1);
		bool flag = false;
		Vector3 localPosition = array[4];
		Vector3 to = Vector3.up;
		for (int i = 0; i < array.Length; i++)
		{
			Vector3 origin = base.transform.TransformPoint(array[i] + Vector3.up * this.superiorLimit);
			RaycastHit raycastHit;
			if (Physics.Raycast(origin, -Vector3.up, out raycastHit, (this.superiorLimit + this.inferiorLimit) * this.cityScale))
			{
				Vector3 vector = base.transform.InverseTransformPoint(raycastHit.point);
				if (!flag || vector.y > localPosition.y)
				{
					localPosition.y = vector.y;
					to = raycastHit.normal;
					flag = true;
					float num = Mathf.Abs(Vector3.Angle(Vector3.up, to));
					if (num > this.maxSlope)
					{
						return false;
					}
				}
			}
		}
		if (flag)
		{
			tile.localPosition = localPosition;
			tile.localPosition.y = tile.localPosition.y + this.streetOffset;
			tile.type = CityBuilder.TileType.Intersection;
			tile.points = array;
		}
		return flag;
	}

	// Token: 0x06001550 RID: 5456 RVA: 0x0008B8B0 File Offset: 0x00089AB0
	private void SpawnIntersection(CityBuilder.Tile tile)
	{
		bool[] array = new bool[4];
		int num = 0;
		int ux = tile.ux;
		int uy = tile.uy;
		array[0] = (uy + 1 < this.diameter && this.tiles[ux, uy + 1].type == CityBuilder.TileType.Road);
		array[1] = (uy - 1 >= 0 && this.tiles[ux, uy - 1].type == CityBuilder.TileType.Road);
		array[2] = (ux - 1 >= 0 && this.tiles[ux - 1, uy].type == CityBuilder.TileType.Road);
		array[3] = (ux + 1 < this.diameter && this.tiles[ux + 1, uy].type == CityBuilder.TileType.Road);
		for (int i = 0; i < 4; i++)
		{
			if (array[i])
			{
				num++;
			}
		}
		GameObject gameObject = null;
		float num2 = 0f;
		switch (num)
		{
		case 1:
			gameObject = UnityEngine.Object.Instantiate<GameObject>(this.endPrefab);
			if (array[1])
			{
				num2 = 180f;
			}
			if (array[2])
			{
				num2 = -90f;
			}
			if (array[3])
			{
				num2 = 90f;
			}
			break;
		case 2:
			if ((array[0] & array[1]) || (array[2] && array[3]))
			{
				gameObject = UnityEngine.Object.Instantiate<GameObject>(this.straightPrefab);
				if (array[2] && array[3])
				{
					num2 = 90f;
				}
			}
			else
			{
				gameObject = UnityEngine.Object.Instantiate<GameObject>(this.curvePrefab);
				if (array[0] && array[2])
				{
					num2 = -90f;
				}
				if (array[1] && array[2])
				{
					num2 = 180f;
				}
				if (array[1] && array[3])
				{
					num2 = 90f;
				}
			}
			break;
		case 3:
			gameObject = UnityEngine.Object.Instantiate<GameObject>(this.junctionPrefab);
			if (!array[0])
			{
				num2 = 90f;
			}
			if (!array[1])
			{
				num2 = -90f;
			}
			if (!array[3])
			{
				num2 = 180f;
			}
			break;
		case 4:
			gameObject = UnityEngine.Object.Instantiate<GameObject>(this.intersectionPrefab);
			break;
		}
		if (gameObject == null)
		{
			return;
		}
		gameObject.transform.SetParent(this.roadRoot.transform, false);
		gameObject.transform.localPosition = tile.localPosition;
		if (num2 != 0f)
		{
			gameObject.transform.localRotation = Quaternion.Euler(0f, num2, 0f);
		}
	}

	// Token: 0x06001551 RID: 5457 RVA: 0x0008BB50 File Offset: 0x00089D50
	private GameObject CheckCloseIntersection(int x, int y)
	{
		int num = this.streetModule;
		CityBuilder.Tile tile = this.tiles[x, y];
		if (x - num > 0)
		{
			CityBuilder.Tile tile2 = this.tiles[x - num, y];
			if (tile2.type == CityBuilder.TileType.Intersection)
			{
				Vector3 vector = tile.localPosition - Vector3.right * this.tileSize / 2f;
				Vector3 vector2 = tile2.localPosition + Vector3.right * this.tileSize / 2f;
				if (Mathf.Abs((vector - vector2).y) < this.tileSize * (float)this.streetModule && this.PlaceRoad(vector, vector2, CityBuilder.Direction.Horizontal))
				{
					this.PlanRoad(tile, tile2);
				}
			}
		}
		if (y - num > 0)
		{
			CityBuilder.Tile tile3 = this.tiles[x, y - num];
			if (tile3.type == CityBuilder.TileType.Intersection)
			{
				Vector3 vector3 = tile.localPosition - Vector3.forward * this.tileSize / 2f;
				Vector3 vector4 = tile3.localPosition + Vector3.forward * this.tileSize / 2f;
				if (Mathf.Abs((vector3 - vector4).y) < this.tileSize * (float)this.streetModule && this.PlaceRoad(vector3, vector4, CityBuilder.Direction.Vertical))
				{
					this.PlanRoad(tile, tile3);
				}
			}
		}
		return null;
	}

	// Token: 0x06001552 RID: 5458 RVA: 0x0008BCE0 File Offset: 0x00089EE0
	private void PlanRoad(CityBuilder.Tile start, CityBuilder.Tile end)
	{
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		if (start.ux == end.ux)
		{
			num = start.ux;
			num2 = start.ux;
			num3 = Mathf.Min(start.uy, end.uy) + 1;
			num4 = Mathf.Max(start.uy, end.uy) - 1;
		}
		if (start.uy == end.uy)
		{
			num3 = start.uy;
			num4 = start.uy;
			num = Mathf.Min(start.ux, end.ux) + 1;
			num2 = Mathf.Max(start.ux, end.ux) - 1;
		}
		for (int i = num; i <= num2; i++)
		{
			for (int j = num3; j <= num4; j++)
			{
				this.tiles[i, j].type = CityBuilder.TileType.Road;
			}
		}
	}

	// Token: 0x06001553 RID: 5459 RVA: 0x0008BDC4 File Offset: 0x00089FC4
	private bool PlaceRoad(Vector3 startPoint, Vector3 endPoint, CityBuilder.Direction direction)
	{
		Vector3 vector = base.transform.TransformPoint(startPoint);
		Vector3 a = base.transform.TransformPoint(endPoint);
		Vector3 vector2 = a - vector;
		float magnitude = vector2.magnitude;
		float magnitude2 = (startPoint - endPoint).magnitude;
		if (Physics.Raycast(vector, vector2, magnitude))
		{
			return false;
		}
		UnityEngine.Debug.DrawRay(vector, vector2, Color.yellow, 60f);
		Vector3 a2;
		if (direction == CityBuilder.Direction.Horizontal)
		{
			a2 = Vector3.forward;
		}
		else
		{
			a2 = Vector3.right;
		}
		Vector3 vector3 = base.transform.TransformPoint(startPoint + a2 * this.tileSize / 4f);
		Vector3 origin = base.transform.TransformPoint(startPoint - a2 * this.tileSize / 4f);
		UnityEngine.Debug.DrawRay(vector3, vector2, Color.yellow, 60f);
		if (Physics.Raycast(vector3, vector2, magnitude))
		{
			return false;
		}
		if (Physics.Raycast(origin, vector2, magnitude))
		{
			return false;
		}
		Vector3 localPosition = (endPoint + startPoint) / 2f;
		GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this.straightPrefab);
		gameObject.transform.SetParent(this.roadRoot.transform, false);
		float f = (Vector3.up * (endPoint.y - startPoint.y)).y / magnitude2;
		float x = Mathf.Asin(f) * 57.29578f;
		gameObject.transform.localPosition = localPosition;
		if (direction == CityBuilder.Direction.Vertical)
		{
			gameObject.transform.localRotation = Quaternion.Euler(x, 0f, 0f);
		}
		else
		{
			gameObject.transform.localRotation = Quaternion.Euler(x, 90f, 0f);
		}
		gameObject.transform.localScale = new Vector3(1f, 1f, magnitude2 / this.tileSize);
		return true;
	}

	// Token: 0x06001554 RID: 5460 RVA: 0x0008BFB4 File Offset: 0x0008A1B4
	private float[,] SamplePerlinNoise(int length)
	{
		float num = UnityEngine.Random.value * 10f;
		float[,] array = new float[length, length];
		float num2 = (float)((length - 1) / 2);
		float num3 = num2 * num2;
		for (int i = 0; i < length; i++)
		{
			for (int j = 0; j < length; j++)
			{
				float num4 = (float)i - num2;
				float num5 = (float)j - num2;
				float num6 = num4 * num4;
				float num7 = num5 * num5;
				float value = 0f;
				if (num6 + num7 < num3)
				{
					Vector2 vector = new Vector2(num4, num5);
					if (this.scaleNoise < 0.3f && vector.magnitude < num2 / 2f)
					{
						value = num2 / 4f / vector.magnitude;
					}
					else
					{
						float num8 = (float)i / (float)length;
						float num9 = (float)j / (float)length;
						float num10 = Mathf.PerlinNoise(num + num8 * this.scaleNoise, num + num9 * this.scaleNoise);
						float num11 = Mathf.PerlinNoise(num + num8 * this.scaleNoise * 2f, num + num9 * this.scaleNoise * 2f);
						float num12 = 1f - vector.magnitude / num2;
						value = (0.5f * num10 + 0.5f * num11) * num12 * 2f;
					}
				}
				array[i, j] = Mathf.Clamp01(value);
			}
		}
		return array;
	}

	// Token: 0x06001556 RID: 5462 RVA: 0x00002973 File Offset: 0x00000B73
	private void UNetVersion()
	{
	}

	// Token: 0x06001557 RID: 5463 RVA: 0x0008C128 File Offset: 0x0008A328
	public override bool OnSerialize(NetworkWriter writer, bool forceAll)
	{
		bool flag = base.OnSerialize(writer, forceAll);
		bool flag2;
		return flag2 || flag;
	}

	// Token: 0x06001558 RID: 5464 RVA: 0x00056DE1 File Offset: 0x00054FE1
	public override void OnDeserialize(NetworkReader reader, bool initialState)
	{
		base.OnDeserialize(reader, initialState);
	}

	// Token: 0x040017DD RID: 6109
	private bool isBuildingsVisible = true;

	// Token: 0x040017DE RID: 6110
	private bool isRoadsVisible = true;

	// Token: 0x040017DF RID: 6111
	private float maxVisibleDistance = 30000f;

	// Token: 0x040017E0 RID: 6112
	private float maxVisibleDistanceRoad = 15000f;

	// Token: 0x040017E1 RID: 6113
	private CityBuilder.Tile[,] tiles;

	// Token: 0x040017E2 RID: 6114
	private float[,] perlinValue;

	// Token: 0x040017E3 RID: 6115
	private GameObject[] buildings0;

	// Token: 0x040017E4 RID: 6116
	private GameObject[] buildings1;

	// Token: 0x040017E5 RID: 6117
	private GameObject[] buildings2;

	// Token: 0x040017E6 RID: 6118
	private GameObject intersectionPrefab;

	// Token: 0x040017E7 RID: 6119
	private GameObject straightPrefab;

	// Token: 0x040017E8 RID: 6120
	private GameObject endPrefab;

	// Token: 0x040017E9 RID: 6121
	private GameObject curvePrefab;

	// Token: 0x040017EA RID: 6122
	private GameObject junctionPrefab;

	// Token: 0x040017EB RID: 6123
	private CityPopulationManager PopManager;

	// Token: 0x040017EC RID: 6124
	private GameObject ColliderPrefab;

	// Token: 0x040017ED RID: 6125
	private CityDestructionManager mDestructionManager;

	// Token: 0x040017EE RID: 6126
	public float buildingDensity = 0.4f;

	// Token: 0x040017EF RID: 6127
	public float tileSize = 15f;

	// Token: 0x040017F0 RID: 6128
	public int radius = 80;

	// Token: 0x040017F1 RID: 6129
	private int diameter;

	// Token: 0x040017F2 RID: 6130
	public int streetModule = 5;

	// Token: 0x040017F3 RID: 6131
	private GameObject buildingRoot;

	// Token: 0x040017F4 RID: 6132
	private GameObject roadRoot;

	// Token: 0x040017F5 RID: 6133
	private GameObject floorRoot;

	// Token: 0x040017F6 RID: 6134
	public float superiorLimit = 300f;

	// Token: 0x040017F7 RID: 6135
	public float inferiorLimit = 100f;

	// Token: 0x040017F8 RID: 6136
	public float maxSlope = 30f;

	// Token: 0x040017F9 RID: 6137
	public float scaleNoise = 1f;

	// Token: 0x040017FA RID: 6138
	public float buildScaleModification = 1f;

	// Token: 0x040017FB RID: 6139
	public float buildingHeightBonus;

	// Token: 0x040017FC RID: 6140
	[SerializeField]
	protected float previewBuildingHeight = 150f;

	// Token: 0x040017FD RID: 6141
	public static float cPerlinThreshold = 0.4f;

	// Token: 0x040017FE RID: 6142
	public const float cMediumThreshold = 0.5f;

	// Token: 0x040017FF RID: 6143
	public const float cTallThreshold = 0.8f;

	// Token: 0x04001800 RID: 6144
	private float populationOffset;

	// Token: 0x04001801 RID: 6145
	private bool seedExists;

	// Token: 0x04001802 RID: 6146
	private int cityGenSeed;

	// Token: 0x04001803 RID: 6147
	private float cityScale = 1f;

	// Token: 0x04001804 RID: 6148
	private float streetOffset = 0.2f;

	// Token: 0x04001805 RID: 6149
	private float floorOffset = 0.1f;

	// Token: 0x04001806 RID: 6150
	public Material floorMaterial;

	// Token: 0x04001807 RID: 6151
	public Material lowPoly;

	// Token: 0x04001808 RID: 6152
	private CityCreationPopUp creationPopup;

	// Token: 0x04001809 RID: 6153
	private bool AutoPopulate;

	// Token: 0x0400180A RID: 6154
	private bool mLowEndMode;

	// Token: 0x0400180B RID: 6155
	private AudioSource audioSource;

	// Token: 0x0400180C RID: 6156
	public float minSoundDistance;

	// Token: 0x0400180D RID: 6157
	public float maxSoundDistance;

	// Token: 0x0400180E RID: 6158
	private Transform placeHolder;

	// Token: 0x0400180F RID: 6159
	private Camera mainCamera;

	// Token: 0x04001810 RID: 6160
	private bool isPlaced;

	// Token: 0x04001811 RID: 6161
	private Collider parentCollider;

	// Token: 0x04001812 RID: 6162
	private List<CityBuilder.Tile> intersections;

	// Token: 0x04001813 RID: 6163
	private readonly SpawningCacheHolder buildingCreationCache = new SpawningCacheHolder();

	// Token: 0x04001814 RID: 6164
	private int cellsPerCycle = 10;

	// Token: 0x02000336 RID: 822
	public enum TileType
	{
		// Token: 0x04001816 RID: 6166
		NoBuild,
		// Token: 0x04001817 RID: 6167
		CanBuild,
		// Token: 0x04001818 RID: 6168
		Intersection,
		// Token: 0x04001819 RID: 6169
		Road,
		// Token: 0x0400181A RID: 6170
		Occupied
	}

	// Token: 0x02000337 RID: 823
	private enum Direction
	{
		// Token: 0x0400181C RID: 6172
		Horizontal,
		// Token: 0x0400181D RID: 6173
		Vertical
	}

	// Token: 0x02000338 RID: 824
	public class Tile
	{
		// Token: 0x06001559 RID: 5465 RVA: 0x0008C141 File Offset: 0x0008A341
		public Tile(int x, int y)
		{
			this.x = x;
			this.y = y;
		}

		// Token: 0x0400181E RID: 6174
		public int x;

		// Token: 0x0400181F RID: 6175
		public int y;

		// Token: 0x04001820 RID: 6176
		public int ux;

		// Token: 0x04001821 RID: 6177
		public int uy;

		// Token: 0x04001822 RID: 6178
		public CityBuilder.TileType type;

		// Token: 0x04001823 RID: 6179
		public Vector3 localPosition;

		// Token: 0x04001824 RID: 6180
		public Vector3[] points;
	}
}
